package com.sky.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.SelectPage;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.constant.TableFieldConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.DishFlavorService;
import com.sky.service.DishService;
import com.sky.utils.ResultUtil;
import com.sky.vo.DishVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * ClassName: DishServiceImpl
 * Description:
 *
 * @Author: Jdz
 * @Create: 2024/1/23 - 19:20
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    private final DishMapper dishMapper;
    private final DishFlavorService dishFlavorService;
    private final SetmealDishMapper setmealDishMapper;

    @Transactional
    @Override
    public Result saveWithFlavor(DishDTO dishDTO) {
        Dish dish = BeanUtil.copyProperties(dishDTO, Dish.class);
        // 向菜品表插入1条数据
        boolean saveResult = super.save(dish);
        // 向口味表插入n条数据
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors != null && flavors.size() > 0) {
            flavors.forEach(dishFlavor -> dishFlavor.setDishId(dish.getId()));
            boolean batchService = dishFlavorService.saveBatch(flavors);
            return ResultUtil.getResult(saveResult && batchService);
        } else {
            return ResultUtil.getResult(saveResult);
        }
    }

    @Override
    public Result<PageResult> pageQuery(DishPageQueryDTO pageQueryDTO) {
        int page = pageQueryDTO.getPage();
        int pageSize = pageQueryDTO.getPageSize();
        String name = pageQueryDTO.getName();
        LambdaQueryWrapper<Dish> wrapper =
                Wrappers.<Dish>query()
                        .eq(ObjUtil.isNotNull(pageQueryDTO.getStatus()), TableFieldConstant.DISH_STATUS, pageQueryDTO.getStatus())
                        .like(StrUtil.isNotBlank(name), TableFieldConstant.DISH_NAME, name)
                        .lambda()
                        .eq(ObjUtil.isNotNull(pageQueryDTO.getCategoryId()), Dish::getCategoryId, pageQueryDTO.getCategoryId())
                        .orderByAsc(Dish::getCreateTime);
        Page<DishVO> pageParam = new Page<>(page, pageSize);
        Page<DishVO> res = dishMapper.pageQuery(pageParam, wrapper);

        return Result.success(new PageResult(res.getTotal(), res.getRecords()));
    }

    @Transactional
    @Override
    public Result deleteBatch(List<Long> ids) {
        ids.forEach(id -> {
            Dish dish = super.getById(id);
            if (Objects.equals(dish.getStatus(), StatusConstant.ENABLE)) {
                // 菜品处于起售中，不可删除
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        });
        // 是否被套餐关联了
        List<SetmealDish> setmealDishes = setmealDishMapper.selectBatchIds(ids);
        if (setmealDishes != null && setmealDishes.size() > 0) {
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        // 删除菜品表中的菜品数据
        boolean r1 = super.removeBatchByIds(ids);
        // 删除菜品关联的口味数据
        boolean r2 = dishFlavorService.remove(Wrappers.<DishFlavor>lambdaQuery()
                .in(DishFlavor::getDishId, ids));
        return ResultUtil.getResult(r1 && r2);
    }

    @Override
    public Result<DishVO> getByIdWithFlavor(Long id) {
        // 查询菜品数据
        Dish dish = super.getById(id);
        // 查询口味数据
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId, id);
        List<DishFlavor> dishFlavors = dishFlavorService.list(wrapper);
        DishVO dishVO = BeanUtil.copyProperties(dish, DishVO.class);
        dishVO.setFlavors(dishFlavors);
        return Result.success(dishVO);
    }

    @Transactional
    @Override
    public Result updateWithFlavor(DishDTO dishDTO) {
        // 修改菜品表基本信息
        boolean r1 = super.updateById(BeanUtil.copyProperties(dishDTO, Dish.class));
        // 删除原有的口味数据(如果有)
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId, dishDTO.getId());
        boolean r2 = dishFlavorService.remove(wrapper);
        // 重新插入口味数据
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors != null && flavors.size() > 0) {
            flavors.forEach(dishFlavor -> dishFlavor.setDishId(dishDTO.getId()));
            boolean batchService = dishFlavorService.saveOrUpdateBatch(flavors);
            return ResultUtil.getResult(r1 && batchService);
        } else {
            return ResultUtil.getResult(r1);
        }
    }

    @Override
    public Result<List<DishVO>> list(Long categoryId, String name) {
        List<Dish> dishes = super.list(Wrappers.<Dish>lambdaQuery()
                .eq(ObjUtil.isNotNull(categoryId), Dish::getCategoryId, categoryId)
                .like(StrUtil.isNotBlank(name), Dish::getName, name)
                .eq(Dish::getStatus, StatusConstant.ENABLE));
        List<DishVO> dishVOS = BeanUtil.copyToList(dishes, DishVO.class);
        return Result.success(dishVOS);
    }

    @Override
    public Result startOrStop(Integer status, Long id) {
        boolean res = super.updateById(Dish.builder().status(status).id(id).build());
        return ResultUtil.getResult(res);
    }


}
